Catalyst / admin/Strike 14.8 GB / 57.8 GB 40.0 GB free
Help Sign in

admin / Strike

public

Web-Based UK Cyber Compliance Tool with Reporting

Code Issues Pull requests Pipelines Packages Security Insights Wiki Settings
Strike / StrikeXi v3 / backend / app / routers / catalogue.py 2170 B · main
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""Read-only catalogue: objectives -> principles -> questions -> options.

v3: scoped to a framework via the ?framework= query parameter (default 'caf'),
so the same questionnaire engine renders any framework's taxonomy.
"""
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session

from .. import models
from ..database import get_db
from ..security import get_current_user

router = APIRouter(prefix="/api/catalogue", tags=["catalogue"])


@router.get("")
def get_catalogue(framework: str = "caf", db: Session = Depends(get_db),
                  user=Depends(get_current_user)):
    objectives = (db.query(models.CafObjective)
                  .filter(models.CafObjective.framework_id == framework)
                  .order_by(models.CafObjective.sort_order).all())
    principles = (db.query(models.CafPrinciple)
                  .filter(models.CafPrinciple.framework_id == framework)
                  .order_by(models.CafPrinciple.sort_order).all())
    principle_ids = {p.id for p in principles}
    questions = [q for q in db.query(models.Question)
                 .order_by(models.Question.sort_order).all()
                 if q.principle_id in principle_ids]
    options = db.query(models.AnswerOption).order_by(models.AnswerOption.sort_order).all()

    opts_by_q = {}
    for o in options:
        opts_by_q.setdefault(str(o.question_id), []).append(
            {"id": str(o.id), "label": o.label, "score": float(o.score)}
        )

    q_by_principle = {}
    for q in questions:
        q_by_principle.setdefault(q.principle_id, []).append({
            "id": str(q.id), "code": q.code, "text": q.text,
            "guidance": q.guidance, "weight": float(q.weight),
            "options": opts_by_q.get(str(q.id), []),
        })

    p_by_obj = {}
    for p in principles:
        p_by_obj.setdefault(p.objective_id, []).append({
            "id": p.id, "title": p.title, "description": p.description,
            "questions": q_by_principle.get(p.id, []),
        })

    return [
        {"id": o.id, "title": o.title, "description": o.description,
         "principles": p_by_obj.get(o.id, [])}
        for o in objectives
    ]